package com.kalvan.log.logback;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.impl.StaticLoggerBinder;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * 日志框架spring 集成
 *
 * @author chenliang
 * @version 2018年4月17日
 * @see LogbackBoot
 */
public class LogbackBoot {
    public static final String LOG_PATH = "logback.logPath";
    public static final String ROOT_LOGGER_LEVEL = "logback.rootLoggerLevel";
    public static final String MAX_FILE_SIZE = "logback.maxFileSize";
    /**
     * Pseudo URL prefix for loading from the class path: "classpath:"
     */
    public static final String CLASSPATH_URL_PREFIX = "classpath:";

    /**
     * 日志路径
     */
    private String logPath;
    /**
     * 日志级别
     */
    private String rootLoggerLevel;
    /**
     * 日志文件分隔大小
     */
    private String maxFileSize;
    /**
     * 日志格式模板配置文件
     */
    private String logbackConfigLocation;

    public String getLogPath() {

        return logPath;
    }

    public void setLogPath(String logPath) {
        this.logPath = logPath;
    }

    public String getRootLoggerLevel() {

        return rootLoggerLevel;
    }

    public void setRootLoggerLevel(String rootLoggerLevel) {
        this.rootLoggerLevel = rootLoggerLevel;
    }

    public String getMaxFileSize() {

        return maxFileSize;
    }

    public void setMaxFileSize(String maxFileSize) {
        this.maxFileSize = maxFileSize;
    }

    public String getLogbackConfigLocation() {

        return logbackConfigLocation;
    }

    public void setLogbackConfigLocation(String logbackConfigLocation) {
        this.logbackConfigLocation = logbackConfigLocation;
    }

    /**
     * 注入动态配置属性<br>
     * 编码默认是utf-8 <br>
     * 输出格式统一%date{yyyy-MM-dd HH:mm:ss.SSS}|%-5level
     * |%t:%threadid|%logTraceId|%class.%method:%line|%sensitiveMsg%n
     */
    public void init() {
        if (StringUtils.isNotBlank(logPath)) {
            System.setProperty(LOG_PATH, logPath.trim());
        }
        // 注入动态配置属性-root日志级别
        if (StringUtils.isNotBlank(rootLoggerLevel)) {
            System.setProperty(ROOT_LOGGER_LEVEL, rootLoggerLevel.trim());
        }
        // 注入动态配置属性-文件分隔大小
        if (StringUtils.isNotBlank(maxFileSize)) {
            System.setProperty(MAX_FILE_SIZE, maxFileSize.trim());
        }
        try {
            URL url = getUrl(logbackConfigLocation);
            LoggerContext loggerContext = (LoggerContext) StaticLoggerBinder
                    .getSingleton().getLoggerFactory();
            // in the current version logback automatically configures at
            // startup
            // the context, so we have to reset it
            loggerContext.reset();
            // reinitialize the logger context. calling this method allows
            // configuration through groovy or xml
            new ContextInitializer(loggerContext).configureByResource(url);
        } catch (FileNotFoundException ex) {
            System.err.println("No logback configuration file found at ["
                    + logbackConfigLocation + "]");
        } catch (JoranException e) {
            throw new RuntimeException(
                    "Unexpected error while configuring logback", e);
        }

    }

    /**
     * Resolve the given resource location to a {@code java.net.URL}.
     * <p>
     * Does not check whether the URL actually exists; simply returns the URL
     * that the given location would correspond to.
     *
     * @param resourceLocation the resource location to resolve: either a "classpath:" pseudo
     *                         URL, a "file:" URL, or a plain file path
     * @return a corresponding URL object
     * @throws FileNotFoundException if the resource cannot be resolved to a URL
     */
    private static URL getUrl(String resourceLocation)
            throws FileNotFoundException {
        if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
            String path = resourceLocation
                    .substring(CLASSPATH_URL_PREFIX.length());
            URL url = Thread.currentThread().getContextClassLoader()
                    .getResource(path);
            if (url == null) {
                String description = "class path resource [" + path + "]";
                throw new FileNotFoundException(description
                        + " cannot be resolved to URL because it does not exist");
            }
            return url;
        }
        try {
            // try URL
            return new URL(resourceLocation);
        } catch (MalformedURLException ex) {
            // no URL -> treat as file path
            try {
                return new File(resourceLocation).toURI().toURL();
            } catch (MalformedURLException ex2) {
                throw new FileNotFoundException("Resource location ["
                        + resourceLocation
                        + "] is neither a URL not a well-formed file path");
            }
        }
    }
}